﻿using System;
using System.Configuration;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;

namespace BlueSky.Web
{
    /// <summary>
    /// HttpApplication base class.
    /// </summary>
    public abstract class HttpApplicationBase : HttpApplication
    { 
        /// <summary>
        /// Unity container.
        /// </summary>
        private IUnityContainer _container = null;

        /// <summary>
        /// Routes registration.
        /// </summary>
        /// <param name="routes">Routes collection.</param>
        protected virtual void RegisterRoutes(RouteCollection routes)
        {
        }

        /// <summary>
        /// ModelBinders registration.
        /// </summary>
        /// <param name="binders">ModelBinder dictionary.</param>
        protected virtual void RegisterModelBinders(ModelBinderDictionary binders)
        {
        }

        /// <summary>
        /// Return Unity container object.
        /// </summary>
        /// <param name="unityFactory">Unity conyainer factory.</param>
        /// <returns>Unity container.</returns>
        protected virtual IUnityContainer GetUnityContainer(UnityContainerFactory unityFactory)
        {
            return unityFactory.Get();
        }

        /// <summary>
        /// Return controller factory object.
        /// </summary>
        /// <param name="container">Unity container.</param>
        /// <returns>Controller factory.</returns>
        protected virtual DefaultControllerFactory GetControllerFactory(IUnityContainer container)
        {
            return new ControllerFactory(container);
        }

        /// <summary>
        /// Starts the application.
        /// </summary>
        public void Application_Start()
        {
            lock (this)
            {
                _container = GetUnityContainer(new UnityContainerFactory());
                
                _container.RegisterInstance<IUnityContainer>(_container, new ContainerControlledLifetimeManager());

                RegisterRoutes(RouteTable.Routes);
                RegisterModelBinders(ModelBinders.Binders);

                ControllerBuilder.Current.SetControllerFactory(GetControllerFactory(_container));
                OnStart();
            }
        }

        /// <summary>
        /// Starts the application.
        /// </summary>
        protected virtual void OnStart()
        {
        }
        

        /// <summary>
        /// Stops the application.
        /// </summary>
        public void Application_Stop()
        {
            lock (this)
            {
                OnStop();

                if (_container != null)
                {                    
                    _container.Dispose();
                    _container = null;
                }
            }
        }

        /// <summary>
        /// Stops the application.
        /// </summary>
        protected virtual void OnStop()
        {            
        }
    }
}
